<script setup lang="ts">
import { useFuse } from '@vueuse/integrations/useFuse';

import { carbonIconComponents } from '@/plugins/icons';
import { BUILT_IN_THEME_PRESETS } from '@/constant';
import { useAppearanceSettingStore } from '@/store/modules/appearance-setting';

const props = defineProps<{
  icon: string | undefined;
}>();
const emits = defineEmits<{
  (e: 'select', value: string | undefined): void;
}>();

const borderRadius = computed(() => useAppearanceSettingStore().borderRadius);

/**
 * 单色图标
 */
const pageSize = 36;
const page = ref(1);
const filterPattern = ref('');
const debouncedPattern = useDebounce(filterPattern, 300);
const { results: carbonIcons } = useFuse<{
  name: string;
  component: Component;
}>(debouncedPattern, markRaw(carbonIconComponents), {
  matchAllWhenSearchEmpty: true,
  fuseOptions: {
    isCaseSensitive: false,
    includeMatches: false,
    findAllMatches: false,
    shouldSort: true,
    keys: ['name'],
  },
});
const searchedCarbonIcons = computed(() => carbonIcons.value.map(result => result.item));
const paginationCarbonIcons = computed(() => {
  const start = (page.value - 1) * pageSize;
  return searchedCarbonIcons.value.slice(start, start + pageSize);
});

function handleSearch(pattern: string) {
  filterPattern.value = pattern;
  page.value = 1;
}

/**
 * 图标风格
 * fill 填充
 * line 线性
 */
const iconStyle = ref('line');
function handleIconStyle(value: string) {
  iconStyle.value = value;
}

/**
 * 图标颜色
 */
const colorList = BUILT_IN_THEME_PRESETS.map(item => item.color);
const iconColor = ref<string>('#000');
function handleSelectColor(color: string) {
  if (iconColor.value === color) {
    iconColor.value = '#000';
  } else {
    iconColor.value = color;
  }
}

watchImmediate(() => props.icon, value => {
  if (value) {
    iconStyle.value = value.split('__')[1] ?? 'line';
    iconColor.value = value.split('__')[2] ?? '#000';
  }
});

/**
 * 图标hover效果
 */
const activeHoverIcon = ref<string>();
function setIcon(name: string) {
  activeHoverIcon.value = name;
}
function clearIcon() {
  activeHoverIcon.value = undefined;
}
const computedIconStyle = computed(() => (name: string) => {
  if (name === activeHoverIcon.value) {
    return {
      color: iconStyle.value === 'fill' ? '#fff' : iconColor.value,
      backgroundColor: iconStyle.value === 'fill' ? iconColor.value : 'transparent',
      borderRadius: borderRadius.value,
      transition: 'all 0.3s',
      transform: 'scale(1.2)',
    };
  } else {
    return {};
  }
});

/**
 * 选择图标
 */
function selectIcon(name: string) {
  const result = `${name}__${iconStyle.value}__${iconColor.value}`;
  emits('select', result);
}
</script>

<template>
  <div>
    <div v-if="searchedCarbonIcons.length > 0" class="px-2">
      <NInput :value="filterPattern" clearable @update:value="handleSearch" />
      <NGrid x-gap="6" y-gap="6" :cols="Math.sqrt(pageSize)" class="mt-2">
        <NGridItem v-for="iconComponent of paginationCarbonIcons" :key="iconComponent.name">
          <div
            class="flex justify-center rounded-md cursor-pointer"
            :style="computedIconStyle(iconComponent.name)"
            @mouseenter="setIcon(iconComponent.name)"
            @mouseleave="clearIcon"
            @click="selectIcon(iconComponent.name)"
          >
            <NIcon class="p-1.5" :size="24" :component="iconComponent.component" />
          </div>
        </NGridItem>
      </NGrid>
      <div class="pt-2 flex justify-between items-center">
        <NRadioGroup v-model:value="iconStyle" @update:value="handleIconStyle">
          <NRadio
            value="fill"
            label="填充"
          />
          <NRadio
            value="line"
            label="线性"
          />
        </NRadioGroup>

        <NPagination
          v-model:page="page"
          simple
          :item-count="searchedCarbonIcons.length"
          :page-size="pageSize"
        />
      </div>
      <div class="flex flex-wrap my-2">
        <div
          v-for="color of colorList"
          :key="color"
          class="w-[16px] h-[16px] rounded mr-2 cursor-pointer"
          :style="{ backgroundColor: color }"
          @click="handleSelectColor(color)"
        />
      </div>
    </div>

    <div v-else class="py-6">
      <NEmpty size="large" description="暂无图标" />
    </div>
  </div>
</template>
